﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using ContactManagement.AppCode;
using ContactManagement.Models.DynamicData;
using ContactMvc4TB.Helpers.HelperClasses;
using EFDataModel;
using Common.Extensions;

namespace ContactMvc4TB.Helpers.DynamicDataType.Creation
{
    /// <summary>
    /// Laden und VErwalten der passenden Lese und Schreibrechte für das jeweilige Dynamische Eingabefeld.
    /// </summary>
    public class DynamicDataRights
    {

        #region Properties
        /// <summary>
        /// Der Aktuelle Dynamische Datentyp, für den die Recht geladen bzw. gesetzt werden sollen
        /// </summary>
        private EFDynamicDataType CurrentDynamicDataType { get; set; }

        /// <summary>
        /// Das aktuelle DynamicDataGroupRightsModel für den Dynamischen DatenTyp, hier werden die Listen direkt im Model gesetzt
        /// </summary>
        private DynamicDataGroupRightsModel CurrentGroupRights { get; set; }

        /// <summary>
        /// Der Aktuelle CurrentController
        /// </summary>
        private Controller CurrentController { get; set; }
        #endregion

        #region Konstruktor
        /// <summary>
        /// Initialisieren des aktuellen DynamicDataRights
        /// </summary>
        /// <param name="dynamicDataTypeId">Der aktuelle Dynamische DatentypId für den die passenden Rechte geladen werden sollen</param>
        /// <param name="groupRights">Das aktuelle EditModel in dem die Lese und Schreibrechte für die Gruppen gesetzt werden sollen</param>
        /// <param name="controller">Der Aktuelle CurrentController</param>
        public DynamicDataRights(int dynamicDataTypeId, DynamicDataGroupRightsModel groupRights, Controller controller)
        {
            //Laden des aktuellen dynamischen Datentyps
            EFDynamicDataType dynamicDataType = CurrentHttpContext.GetDataModel().EFDynamicDataTypeMenge.Find(dynamicDataTypeId);
            if (dynamicDataType != null)
            {
                CurrentDynamicDataType = dynamicDataType;
                groupRights.CurrentDynamicDataType = CurrentDynamicDataType;
            }
            else
            {
                throw new Exception("Der dynamische Datentyp konnte nicht gefunden werden!");
            }

            CurrentGroupRights = groupRights;
            CurrentController = controller;
        }
        #endregion

        #region Public Functions
        /// <summary>
        /// Laden aller Rechte für den aktuellen Datentyp, es wird im EditModel gesetzt, welche Gruppen Lese und welche schreibrechte auf das aktuelle Eingabefeld haben 
        /// </summary>
        public DynamicDataGroupRightsModel LoadReadWriteRightsForModel()
        {
            //ACHTUNG die reihenfolge der Aufrufe ist Wichtig!
            //Laden der LeseRechte für den Datentyp
            GroupsWithReadRights();
            //Laden der Schreibrechte für den DatenTyp
            GroupsWithWriteRights();
            //Alle Gruppen die noch nicht den Leserechten zugewiesen wurden
            GroupsNotWithReadRights();
            //Alle Gruppen die nocht nicht den Schreib/Leserechten zugewiesen wurden
            GroupsNotWithWriteRights();

            return CurrentGroupRights;
        }

        /// <summary>
        /// Eine Gruppe zu den Leserechten hinzufügen
        /// </summary>
        /// <param name="groupId">Die Gruppe die zu den Leserechten hinzugefügt werden soll</param>
        public void AddGroupToReadRights(int groupId)
        {
            SetGroupChanges(groupId, EActionDynamicData.AddGroupReadRight);
        }

        /// <summary>
        /// Eine Gruppe zu den Lese/Schreibrechten hinzufügen
        /// </summary>
        /// <param name="groupId">Die Gruppe die zu den Lese/Schreibrechten hinzugefügt werden soll</param>
        public void AddGroupToWriteRights(int groupId)
        {
            SetGroupChanges(groupId, EActionDynamicData.AddGroupWriteRight);
        }

        /// <summary>
        /// Die gruppe von den Lese/Schreibrechten Entfernen
        /// </summary>
        /// <param name="groupId">Die Gruppe die entfernt werden soll</param>
        public void DeleteGroupFromWriteRights(int groupId)
        {
            SetGroupChanges(groupId, EActionDynamicData.DeleteGroupWriteRight);
        }

        /// <summary>
        /// Die Gruppe von den Leserechten Entfernen
        /// </summary>
        /// <param name="groupId">Die Gruppe entfernt werden soll</param>
        public void DeleteGroupFromReadRights(int groupId)
        {
            SetGroupChanges(groupId, EActionDynamicData.DeleteGroupReadRight);
        }
        #endregion

        #region Private Functions
        /// <summary>
        /// Setzten der passenden Gruppenrechte Änderungen von Lesen und Schreiben für die jeweilige Gruppe
        /// </summary>
        /// <param name="groupId">GruppenId die Hinzugefügt oder entfernt werden soll</param>
        /// <param name="actionDynamicData">Die Aktion die ausgeführt werden soll</param>
        private void SetGroupChanges(int groupId, EActionDynamicData actionDynamicData)
        {
            //Die Gruppe herraussuchen die Hinzugefügt werden soll
            var group = (UserGroup)CurrentHttpContext.GetDataModel().EFCategoryMenge.Find(groupId);
            if (group != null)
            {
                try
                {
                    //Je nach Aktion die ausgeführt werden soll, die passende Liste mit Daten füllen oder Daten löschen
                    switch (actionDynamicData)
                    {
                        case EActionDynamicData.AddGroupReadRight:
                            //Hinzufügen der Usergruppe
                            CurrentDynamicDataType.UserGroupsRead.Add(group);
                            break;

                        case EActionDynamicData.AddGroupWriteRight:
                            //Hinzufügen der Usergruppe
                            CurrentDynamicDataType.UserGroupsWrite.Add(group);
                            break;

                        case EActionDynamicData.DeleteGroupReadRight:
                            //Entfernen der Usergruppe
                            CurrentDynamicDataType.UserGroupsRead.Remove(group);
                            break;

                        case EActionDynamicData.DeleteGroupWriteRight:
                            //Entfernen der Usergruppe
                            CurrentDynamicDataType.UserGroupsWrite.Remove(group);
                            break;
                    }

                    //Speichern der Einstellungen
                    CurrentHttpContext.GetDataModel().SaveChanges();
                    EFDynamicDataType.ResetDynamicDataTypeList();

                    //Erfolgsmeldung anzeigen
                    switch (actionDynamicData)
                    {
                        case EActionDynamicData.AddGroupReadRight:
                        case EActionDynamicData.AddGroupWriteRight:
                            CustomMessage.CurrentMessage(CurrentController).AddMessage(GlobalResources.SystemMessages.DynamicDataGroupAddedSuccessfullyRESX, MessageTypes.ok);
                            break;

                        case EActionDynamicData.DeleteGroupReadRight:
                        case EActionDynamicData.DeleteGroupWriteRight:
                            CustomMessage.CurrentMessage(CurrentController).AddMessage(GlobalResources.SystemMessages.DynamicDataGroupDeletedSuccessfullyRESX, MessageTypes.ok);
                            break;
                    }
                }
                catch (Exception exception)
                {
                    EFDebugging.Debugging.WriteLog(exception);
                    //Wenn ein  Fehler aufgetreten ist, diesen anzeigen
                    CustomMessage.CurrentMessage(CurrentController).AddMessage(GlobalResources.SystemMessages.ErrorPleaseTryAgainRESX, MessageTypes.error);
                }
            }
            else
            {
                //Die gruppe konnte nicht gefunden werden
                CustomMessage.CurrentMessage(CurrentController).AddMessage(GlobalResources.SystemMessages.GroupNotFoundRESX, MessageTypes.error);
            }
        }

        /// <summary>
        /// Gibt alle UserGruppen zurück die Leserechte für diese Gruppe besitzten
        /// </summary>
        private void GroupsWithReadRights()
        {
            //Für den aktuellen DatenTyp alle Gruppen heraussuchen die lesen dürfen.
            var readRights = from efDynamicDataType in CurrentDynamicDataType.UserGroupsRead select efDynamicDataType;
            CurrentGroupRights.GroupsWithReadRights = readRights.OrderByUrlParams();
        }

        /// <summary>
        /// Alle Gruppen die noch nicht in der Liste mit den Leserechten für diesen Datentyp sind
        /// </summary>
        private void GroupsNotWithReadRights()
        {
            //Alle Gruppen heraussuchen die existieren und dann mit der Gruppe abgleichen in der alle Personen enthalten sind
            var groups = from eUserGroup in CurrentHttpContext.GetDataModel().EFCategoryMenge.OfType<UserGroup>() select eUserGroup;
            List<UserGroup> groupsNotWithReadRights = new List<UserGroup>();

            //Alle UserGruppen druchgehen und prüfen welche nicht enthalten sind.
            foreach (UserGroup eUserGroup in groups)
            {
                if (!CurrentGroupRights.GroupsWithReadRights.Contains(eUserGroup))
                {
                    groupsNotWithReadRights.Add(eUserGroup);
                }
            }

            //Setzten der passenden AUfListung
            CurrentGroupRights.GroupsNotWithReadRights = groupsNotWithReadRights.OrderByUrlParams();
        }

        /// <summary>
        /// Gibt alle UserGruppen zurück die Schreibrechte für diese Gruppe besitzten
        /// </summary>
        private void GroupsWithWriteRights()
        {
            //Für den aktuellen DatenTyp alle Gruppen heraussuchen die schreiben/lesen dürfen.
            var readRights = from efDynamicDataType in CurrentDynamicDataType.UserGroupsWrite select efDynamicDataType;
            CurrentGroupRights.GroupsWithWriteRights = readRights.OrderByUrlParams();
        }

        /// <summary>
        /// Alle Gruppen die noch nicht in den Schreibrechten/Leserechten für diese Gruppe sind.
        /// </summary>
        private void GroupsNotWithWriteRights()
        {
            //Alle Gruppen heraussuchen die existieren und dann mit der Gruppe abgleichen in der alle Personen enthalten sind
            var groups = from eUserGroup in CurrentHttpContext.GetDataModel().EFCategoryMenge.OfType<UserGroup>() select eUserGroup;
            List<UserGroup> groupsNotWithWriteRights = new List<UserGroup>();

            //Alle UserGruppen druchgehen und prüfen welche nicht enthalten sind.
            foreach (UserGroup eUserGroup in groups)
            {
                if (!CurrentGroupRights.GroupsWithWriteRights.Contains(eUserGroup))
                {
                    groupsNotWithWriteRights.Add(eUserGroup);
                }
            }

            //Setzten der passenden AufListung
            CurrentGroupRights.GroupsNotWithWriteRights = groupsNotWithWriteRights.OrderByUrlParams();
        }
        #endregion
    }
}